package dao

import (
	"haiqiu-go-admin/entity"
	"haiqiu-go-admin/entity/dto"
	"haiqiu-go-admin/utils"
	"log"
	"strconv"
	"strings"
)

// NoticeById 根据ID查询数据
func NoticeById(id int64) (*entity.SysNotice, error) {
	row := DB.QueryRow("select * from sys_notice where id = ?", id)
	var sysNotice entity.SysNotice
	err := row.Scan(
		&sysNotice.Id,
		&sysNotice.Title,
		&sysNotice.Content,
		&sysNotice.Sort,
		&sysNotice.Username,
		&sysNotice.View,
		&sysNotice.Cover,
		&sysNotice.Type,
		&sysNotice.CreateTime,
		&sysNotice.UpdateTime,
		&sysNotice.Status,
	)
	if err != nil {
		panic(err)
	}
	return &sysNotice, nil
}

// NoticePageCount 分页查询总条数
func NoticePageCount(page dto.NoticeQueryDto) (count int64) {
	wrapper := utils.QueryWrapper().Count("sys_notice")
	getNoticeCondition(&page, wrapper)
	err := DB.QueryRow(wrapper.GetSql(), wrapper.GetVal()...).Scan(&count)
	if err != nil {
		log.Println(err.Error())
	}
	return count
}

// NoticePageList 分页查询数据
func NoticePageList(page dto.NoticeQueryDto) (*[]entity.SysNotice, error) {
	wrapper := utils.QueryWrapper().Page("sys_notice", page.PageIndex, page.PageSize)
	getNoticeCondition(&page, wrapper)
	rows, err := DB.Query(wrapper.GetSql(), wrapper.GetVal()...)
	if err != nil {
		log.Println(err.Error())
		return nil, err
	}
	var sysNotices []entity.SysNotice
	for rows.Next() {
		var sysNotice = entity.SysNotice{}
		err := rows.Scan(
			&sysNotice.Id,
			&sysNotice.Title,
			&sysNotice.Content,
			&sysNotice.Sort,
			&sysNotice.Username,
			&sysNotice.View,
			&sysNotice.Cover,
			&sysNotice.Type,
			&sysNotice.CreateTime,
			&sysNotice.UpdateTime,
			&sysNotice.Status,
		)
		if err != nil {
			log.Println(err.Error())
			return nil, err
		}
		sysNotices = append(sysNotices, sysNotice)
	}
	return &sysNotices, nil
}

func getNoticeCondition(page *dto.NoticeQueryDto, wrapper *utils.Wrapper) {
	if page.Params.Username != nil {
		wrapper.Eq("username", *page.Params.Username)
	}
	if page.Params.Title != nil {
		wrapper.Like("title", *page.Params.Title)
	}
	if page.Params.Type != nil {
		wrapper.Eq("type", *page.Params.Type)
	}
	if page.Params.BeginTime != nil && page.Params.EndTime != nil {
		wrapper.Between("create_time", *page.Params.BeginTime,
			*page.Params.EndTime)
	}
}

// NoticeAdd 新增数据
func NoticeAdd(sysNotice *entity.SysNotice) (int64, error) {
	exec, err := DB.Exec("insert into `sys_notice` "+
		"(`id`, `title`, `content`, `sort`, `username`, `view`, `cover`, "+
		"`type`, `create_time`, `update_time`, `status` ) "+
		"values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )",
		&sysNotice.Id,
		&sysNotice.Title,
		&sysNotice.Content,
		&sysNotice.Sort,
		&sysNotice.Username,
		&sysNotice.View,
		&sysNotice.Cover,
		&sysNotice.Type,
		&sysNotice.CreateTime,
		&sysNotice.UpdateTime,
		&sysNotice.Status,
	)
	if err != nil {
		return 0, err
	}
	rowsAffected, err := exec.RowsAffected()
	if err != nil {
		return 0, err
	}
	return rowsAffected, nil
}

// NoticeUpdate 根据ID更新数据
func NoticeUpdate(sysNotice *entity.SysNotice) (int64, error) {
	exec, err := DB.Exec("update `sys_notice` set  `title` = ?, `content` = ?, "+
		"`sort` = ?, `username` = ?, `view` = ?, `cover` = ?, `type` = ?, "+
		"`create_time` = ?, `update_time` = ?, `status` = ? where `id` = ? ",
		&sysNotice.Title,
		&sysNotice.Content,
		&sysNotice.Sort,
		&sysNotice.Username,
		&sysNotice.View,
		&sysNotice.Cover,
		&sysNotice.Type,
		&sysNotice.CreateTime,
		&sysNotice.UpdateTime,
		&sysNotice.Status,
		&sysNotice.Id,
	)
	if err != nil {
		panic(err)
		return 0, err
	}
	rowsAffected, err := exec.RowsAffected()
	if err != nil {
		panic(err)
		return 0, err
	}
	return rowsAffected, nil
}

// NoticeDelete 根据ID删除数据
func NoticeDelete(id int64) (int64, error) {
	exec, err := DB.Exec("delete from sys_notice where id = ?")
	if err != nil {
		panic(err)
		return 0, err
	}
	rowsAffected, err := exec.RowsAffected()
	if err != nil {
		panic(err)
		return 0, err
	}
	return rowsAffected, nil
}

// NoticeDeleteBatch 根据ID批量删除数据
func NoticeDeleteBatch(ids []int64) (int64, error) {
	var idsStr string
	for index, id := range ids {
		if index == len(ids)-1 {
			idsStr += strconv.FormatInt(id, 10)
		} else {
			idsStr += strconv.FormatInt(id, 10) + ", "
		}
	}
	exec, err := DB.Exec("delete from sys_notice where id in (?)", idsStr)
	if err != nil {
		panic(err)
		return 0, err
	}
	rowsAffected, err := exec.RowsAffected()
	if err != nil {
		panic(err)
		return 0, err
	}
	return rowsAffected, nil
}

// NoticeList 查询所有数据
func NoticeList() (*[]entity.SysNotice, error) {
	rows, err := DB.Query("select * from sys_notice")
	if err != nil {
		panic(err)
		return nil, err
	}
	var sysNotices []entity.SysNotice
	for rows.Next() {
		var sysNotice entity.SysNotice
		err := rows.Scan(
			&sysNotice.Id,
			&sysNotice.Title,
			&sysNotice.Content,
			&sysNotice.Sort,
			&sysNotice.Username,
			&sysNotice.View,
			&sysNotice.Cover,
			&sysNotice.Type,
			&sysNotice.CreateTime,
			&sysNotice.UpdateTime,
			&sysNotice.Status,
		)
		if err != nil {
			panic(err)
			return nil, err
		}
		sysNotices = append(sysNotices, sysNotice)
	}
	return &sysNotices, nil
}

func ActiveNoticeById(sysNotices []entity.SysNotice) (any, error) {
	var ids strings.Builder
	var active = sysNotices[0].Status
	for index, value := range sysNotices {
		if index == len(sysNotices) {
			ids.WriteString(strconv.FormatInt(value.Id, 10))
		} else {
			ids.WriteString(strconv.FormatInt(value.Id, 10))
		}
	}
	exec, err := DB.Exec("update sys_notice set status = ? where id in ( ? )", active, ids.String())
	if err != nil {
		panic(err)
		return nil, err
	}
	rowsAffected, err := exec.RowsAffected()
	if err != nil {
		panic(err)
		return nil, err
	}
	return rowsAffected, nil
}

func StatisticsNotice() (any, error) {
	rows, err := DB.Query("SELECT CASE `type` WHEN 0 THEN '公告' WHEN 1 THEN '通知' ELSE '日志' END AS typeName, `type`, count( id ) AS `count` FROM `sys_notice` GROUP BY type")
	if err != nil {
		panic(err)
	}
	// 数据列
	columns, err := rows.Columns()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	// 列的个数
	count := len(columns)

	// 返回值 Map切片
	mData := make([]map[string]interface{}, 0)
	// 一条数据的各列的值（需要指定长度为列的个数，以便获取地址）
	values := make([]interface{}, count)
	// 一条数据的各列的值的地址
	valPointers := make([]interface{}, count)
	for rows.Next() {

		// 获取各列的值的地址
		for i := 0; i < count; i++ {
			valPointers[i] = &values[i]
		}

		// 获取各列的值，放到对应的地址中
		rows.Scan(valPointers...)

		// 一条数据的Map (列名和值的键值对)
		entry := make(map[string]interface{})

		// Map 赋值
		for i, col := range columns {
			var v interface{}

			// 值复制给val(所以Scan时指定的地址可重复使用)
			val := values[i]
			b, ok := val.([]byte)
			if ok {
				// 字符切片转为字符串
				v = string(b)
			} else {
				v = val
			}
			entry[col] = v
		}

		mData = append(mData, entry)
	}

	return mData, nil
}
